#include "netcore.h"

NetCore::NetCore()
{
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, &QTcpSocket::connected, this , &NetCore::on_tcp_connect);
    connect(tcpSocket, &QTcpSocket::readyRead, this , &NetCore::on_tcp_read);
    connect(tcpSocket, &QTcpSocket::disconnected, this, &NetCore::on_tcp_disconnect);
}


void NetCore::config(QString host, int port)
{
    this->host = host;
    this->port = port;
}

void NetCore::start()
{
    tcpSocket->abort();
    tcpSocket->connectToHost(host, port, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
    // 设置连接超时
    QTimer * timer = new QTimer(this);
    connect(timer,&QTimer::timeout,[=](){
        if(tcpSocket->state() == QAbstractSocket::ConnectingState)
        {
            tcpSocket->close();
            emit this->sigError(ERR_NETTIMEOUT, "服务器连接超时");
        }
        timer->stop();
    });
    timer->start(3000);
}

void NetCore::stop()
{
    tcpSocket->close();
}

void NetCore::sendScData(int x, int y, QByteArray data)
{
    // 将位图块的坐标信息写入数据流
    QByteArray mapData;
    mapData.resize(2);
    mapData[0] = x;
    mapData[1] = y;
    mapData.append(data);

    // 发送数据
    tcpSocket->write(mkPkg(mapData));
    tcpSocket->flush();
}

// ***********************  以下是网络通讯槽函数 *****************************
// 服务器链接 - 接收数据槽函数
void NetCore::on_tcp_read()
{
    QTcpSocket *tmpTcpSocket = (QTcpSocket*)sender();
//    qDebug() << "接收消息" << tmpTcpSocket->readAll();
    unPkg(tmpTcpSocket->readAll());
}

void NetCore::on_tcp_connect()
{
    qDebug() << "服务器连接成功";
    emit this->sigServer(NET_CONNECTED,
                         QString("服务器连接成功[%1 %2]")
                         .arg(tcpSocket->peerAddress().toString())
                         .arg(tcpSocket->peerPort()));
}

void NetCore::on_tcp_disconnect()
{
    qDebug() << "与服务器链接断开";
    emit this->sigServer(NET_DISCONNECT, "服务器链接断开");
}

void NetCore::pkgReady(QByteArray data)
{
    QJsonDocument jsonDocument = QJsonDocument::fromJson(data);
    if(!jsonDocument.isNull())
    {
        QJsonObject rootObject = jsonDocument.object();
        // 配置信息json
        if(!rootObject.value("cmd").isNull() && rootObject.value("cmd") == "config")
        {
            QJsonObject jsonObject = rootObject.value("data").toObject();
            int scWidth = jsonObject.value("width").isNull() ? 0 : jsonObject.value("width").toInt();
            int scHeight = jsonObject.value("height").isNull() ? 0 : jsonObject.value("height").toInt();
            int indexX = jsonObject.value("x").isNull() ? 0 : jsonObject.value("x").toInt();
            int indexY = jsonObject.value("y").isNull() ? 0 : jsonObject.value("y").toInt();
            int bit = jsonObject.value("bit").isNull() ? 0 : jsonObject.value("bit").toInt();
            int fps = jsonObject.value("fps").isNull() ? 0 : jsonObject.value("fps").toInt();

            // 通知上层UI屏幕配置信息
            emit this->sigScConfig(scWidth, scHeight, indexX, indexY, bit, fps);
        }
        // 网络延时信息json
        else if(!rootObject.value("cmd").isNull() && rootObject.value("cmd") == "delay")
        {
            QJsonObject jsonObject = rootObject.value("data").toObject();
            QString send = jsonObject.value("send").isNull() ? "0" : jsonObject.value("send").toString();
            qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
            QJsonObject sendRootObject;
            QJsonObject sendItemObject;
            sendItemObject.insert("send", send);
            sendItemObject.insert("recv", QString("%1").arg(timestamp));
            sendRootObject.insert("cmd", "delay");
            sendRootObject.insert("data", sendItemObject);
            QJsonDocument doc(sendRootObject);
            tcpSocket->write(mkPkg(doc.toJson(QJsonDocument::Compact)));
            tcpSocket->flush();
        }
        // 停止抓屏发包命令
        else if(!rootObject.value("cmd").isNull() && rootObject.value("cmd") == "scsig")
        {
            QJsonObject jsonObject = rootObject.value("data").toObject();
            int code = jsonObject.value("code").isNull() ? 0 : jsonObject.value("code").toInt();
            emit this->sigScSig(code);
        }
        else
        {
            emit this->sigError(ERR_FORMAT, "错误的数据包" + QString(data));
        }
    }else
    {
        emit this->sigError(ERR_FORMAT, "错误的数据包" + QString(data));
    }
}
